/*****************************************************************************
*                  Shanghai ChipON Micro-Electronic Co.,Ltd                  *
******************************************************************************
*  @File Name        : CMP.c                                                 *
*  @Author           : ChipON AE/FAE Group                                   *
*  @Data$            : 2021-07-14                                            *
*  @Version          : V2.0                                                  *
*  @Description      : This file contains the CMP interrupt configuration    *
*                      for KF32A156 devices                                  *
******************************************************************************
*  Copyright (C) by Shanghai ChipON Micro-Electronic Co.,Ltd                 *
*  All rights reserved.                                                      *
*                                                                            *
*  This software is copyright protected and proprietary to                    *
*  Shanghai ChipON Micro-Electronic Co.,Ltd.                                 *
******************************************************************************
*  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  *
*                          REVISON HISTORY                                   *
*  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  *
*  Data       Version  Author        Description                             *
*  ~~~~~~~~~~ ~~~~~~~~ ~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  *
*  2021-07-14 00.02.00  AE Group     Version 2.0 update                      *
*                                                                            *
*                                                                            *
*****************************************************************************/

/******************************************************************************
**                             Include Files                                **
******************************************************************************/
#include "CMP.h"

/*****************************************************************************
**                         Private Macro Definitions                        **
*****************************************************************************/

/*****************************************************************************
**                         Private Variables Definitions                    **
*****************************************************************************/
uint32_t CMP0_Trim_N = 0;
uint32_t CMP0_Trim_P = 0;
/*****************************************************************************
**                             Private Functions                            **
*****************************************************************************/

/*****************************************************************************
**                             Global Functions                            **
*****************************************************************************/
/**
 *  @brief: Initialize CMP Hw Module
 *  @param in: 
 *  @param out : None
 *  @retval : None
 */
void CMP_Init()
{
    CMP_InitTypeDef Cmp_ConfigPtr;

    /* CMP reset */
    CMP_Reset();

    /* Cmp positive terminal output selection bit */
    Cmp_ConfigPtr.m_PositiveInput = CMP3_PositiveINPUT_PIN_PA0;
    /* Cmp negative terminal output selection bit */
    Cmp_ConfigPtr.m_NegativeInput = CMP3_NegativeINPUT_PIN_PC6;
    /* Enable comparator falling edge trigger interrupt */
    Cmp_ConfigPtr.m_FallTriggerEnable = TRUE;
    /* Enable comparator rising edge to trigger interrupt */
    Cmp_ConfigPtr.m_RiseTriggerEnable = TRUE;
    /* Cmp filter filter clock source */
    Cmp_ConfigPtr.m_Clock = CMPx_CLKSOURCE_HFCLK;
    /* Cmp filter filtering time division frequency */
    Cmp_ConfigPtr.m_FrequencyDivision = 0x00;
    /* Sampling number selection */
    Cmp_ConfigPtr.m_SampleNumber = CMPx_FLT_OFF;
    /* Filter enable bit */
    Cmp_ConfigPtr.m_FilterEnable = FALSE;
    /* Cmp range control enable bit */
    Cmp_ConfigPtr.m_ScopecontrolEnable = FALSE;
    /* Output polarity selection */
    Cmp_ConfigPtr.m_OutputPolarity = CMPx_OUTPUT_Normal;
    /* Cmp module enable */
    Cmp_ConfigPtr.m_CmpEnable = TRUE;

    /* Configure CMP3 */
    CMP_Configuration(CMP3_ADDR, &Cmp_ConfigPtr);

//	/* Enable CMP0 */
//    CMP_CTL4 |= 0x00000021;
	
    /* Enable IO channel */
    CMP_IO_Channel_Enable(TRUE);
}

/**
 *  @brief: CMP interrupt inialization
 *  @param in: 
 *  @param out : None
 *  @retval : None
 */
void CMP_Interrupt_Init(void)
{
    /* Trigger the interrupt flag by detecting the output change edge of the comparator */
    CMP_Trigger_Select_Config(CMP_CMPOUT_Change_INT);
    /* Enable CMP3 interrupt */
    CMP_INT_Enable(CMP3_ADDR, TRUE);

    /* Preemption priority 4, sub-priority 0 */
    INT_Interrupt_Priority_Config(INT_CMP, 4, 0);
    /* Peripheral interrupt enable */
    INT_Interrupt_Enable(INT_CMP, TRUE);
    /* Clear interrupt flag */
    INT_Clear_Interrupt_Flag(INT_CMP);
    /* Interrupt automatic stack using single word alignment */
    INT_Stack_Align_Config(INT_STACK_SINGLE_ALIGN);
    /* Enable global interrupt */
    INT_All_Enable(TRUE);
}

/**
 *  @brief: CMP IO inialization
 *  @param in: 
 *  @param out : None
 *  @retval : None
 */
void CMP_IO_Init()
{
    /* CMP IO inialization:C3OUT PA11 */
    GPIO_Write_Mode_Bits(GPIOA_SFR, GPIO_PIN_MASK_11, GPIO_MODE_RMP);
    GPIO_Pin_RMP_Config(GPIOA_SFR, GPIO_Pin_Num_11, GPIO_RMP_PG1_AF11);

	GPIO_Write_Mode_Bits(GPIOC_SFR,GPIO_PIN_MASK_6,GPIO_MODE_AN);
	GPIO_Write_Mode_Bits(GPIOA_SFR,GPIO_PIN_MASK_0,GPIO_MODE_AN);	//CONFIG  IO   AN MODE
}

/**
 *  @brief: CMP calibration function
 *  @param in: 
 *  @param out : None
 *  @retval : None
 */
void CMP_Calibration(void)
{

    /* CMP reset */
    CMP_Reset();

    /* Calibration PMOS */
    /* Enable CMPTRIMLOW */
    CMP_TRIM0 |= 0x40000000;

    /* Delay time */
    delay_ms(12);

    /* If CMO0_OUT output is high */
    if (CMP_CTL4 & 0x10000000)
    {
        /* C0TRIMPOL set to 0, negative calibration */
        CMP_TRIM0 &= 0xFFFFF7FF;
        /* Delay time */
        delay_ms(12);
        for (uint16_t i = 1; i < 33; i++)
        {
            /* CMP0_OUT level is detected to be turned to 0 */
            if (!(CMP_CTL4 & 0x10000000))
            {
                break;
            }
             CMP_TRIM0 |= 0X100 * i;
            delay_ms(12);
        }
    }
    /* If CMO0_OUT output is low */
    else if (!(CMP_CTL4 & 0x10000000))
    {
        /* C0TRIMPOL set to 1, positive calibration */
        CMP_TRIM0 |= 0x00000080;
        /* Delay time */
        delay_ms(12);
        for (uint16_t j = 1; j < 33; j++)
        {
            /* CMP0_OUT level is detected to be turned to 1 */
            if (CMP_CTL4 & 0x10000000)
            {
                break;
            }
             CMP_TRIM0 |= 0x100 * j;
            delay_ms(12);
        }
    }

    CMP0_Trim_P = CMP_TRIM0;

    /* Register initialization */
    CMP_TRIM0 &= 0;
    /* Calibration NMOS */
    CMP_TRIM0 |= 0x80000000;
    delay_ms(12);
    /* If CMO0_OUT output is high */
    if (CMP_CTL4 & 0x10000000)
    {
        /* C0TRIMNPOL set to 1, positive calibration */
        CMP_TRIM0 |= 1;
        for (uint8_t i = 1; i < 33; i++)
        {
            /* C0TRIMNPOL set to 0, negative calibration */
            if (!(CMP_CTL4 & 0x10000000))
            {
                break;
            }
             CMP_TRIM0 = CMP_TRIM0 | 0x2 * i;
            delay_ms(12);
        }
    }
    /* If CMO0_OUT output is high */
    else if (!(CMP_CTL4 & 0x10000000))
    {
        /* C0TRIMNPOL set to 0, positive calibration */
        CMP_TRIM0 &= 0xFFFFFFFE;
        for (uint8_t j = 1; j < 33; j++)
        {
            /* C0TRIMNPOL set to 0, negative calibration */
            if (CMP_CTL4 & 0x10000000)
            {
                break;
            }
             CMP_TRIM0 = CMP_TRIM0 | 0x2 * j;
            delay_ms(12);
        }
    }
    CMP0_Trim_N = CMP_TRIM0;

    /* Write calibration value */
    CMP_TRIM0 = (CMP0_Trim_P & 0x00003F00) | (CMP0_Trim_N & 0x0000007E);
}

/**
 *  @brief: Delay time
 *  @param in:
 *  @param out : None
 *  @retval : None
 */
void delay_ms(volatile uint32_t nms)
{
    volatile uint32_t i, j;
    for (i = 0; i < nms; i++)
    {
        j = 2000;
        while (j--)
            ;
    }
}
